package com.abc.xxx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.abc.xxx.dao.AccessibleViewMapper;
import com.abc.xxx.model.AccessibleView;
import com.abc.xxx.model.View;
import com.abc.xxx.model.vo.AccessiblePage;
import com.abc.xxx.model.vo.PermissionAssignment;
import com.abc.xxx.service.AccessibleViewService;
import com.abc.xxx.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Slf4j
@Service
public class AccessibleViewServiceImpl extends ServiceImpl<AccessibleViewMapper, AccessibleView> implements AccessibleViewService {


    @Override
    public List<String> findRoleAccessibleViews(Integer roleId) {
        QueryWrapper<AccessibleView> w = new QueryWrapper<>();
        w.select("`view_code`");
        w.eq("role_id", roleId);
        w.orderByAsc("`view_code`");
        List<String> codes = listObjs(w, obj -> (String) obj);
        return codes;
    }

    /**
     * 转换成 页面权限 - 按钮权限 的树状结构
     *
     * @param views
     * @return
     */
    public List<AccessiblePage> convertToPageButtonTree(List<View> views) {
        log.info("数据结构转换: 页面、按钮权限List --> Tree");
        return views.stream()
                .filter(v1 -> v1.isPage())
                .map(page -> {
                    String pageCode = page.getCode();
                    List<String> buttonCodes = views.stream()
                            .filter(v2 -> v2.isButton() && v2.isChildOf(pageCode))
                            .map(button -> button.getCode()).collect(Collectors.toList());
                    return new AccessiblePage(pageCode, buttonCodes);
                })
                .collect(Collectors.toList());
    }

    @Override
    public boolean deleteRelation(String roleCode, Integer permissionType) {
        QueryWrapper<AccessibleView> w = new QueryWrapper<>();
        w.eq("role_code", roleCode);
        w.eq("type", permissionType);
        return remove(w);
    }

    @Transactional
    @Override
    public void assignPageAndButtonPermissions(Integer roleId, List<AccessibleView> accessibleViews) {
        log.info("step_1: 删除角色原来关联的菜单、按钮");
        QueryWrapper<AccessibleView> dw = new QueryWrapper<>();
        dw.eq("role_id", roleId);
        remove(dw);

        log.info("step_2: 重新添加角色关联的菜单、按钮");
        accessibleViews.forEach(av -> {
            av.setRoleId(roleId);
        });
        saveBatch(accessibleViews);
    }

    @Transactional
    @Override
    public Result assignButtonPermissions(String oper, PermissionAssignment form) {
        final Integer roleId = form.getRole();
        final String pageCode = form.getPage();
        if (roleId == null) {
            return Result.error(oper).msg("角色id不能为空");
        }
        if (StringUtils.isBlank(pageCode)) {
            return Result.error(oper).msg("页面标识码不能为空");
        }
        //不校验codes，允许codes为空，表示清除该角色关联的权限

        log.info("step_1: 删除按钮归属的页面({})下原来已关联的按钮权限", pageCode);
        if (StringUtils.isNotBlank(pageCode)) {
            deleteRoleRelatedButtonsByPageCodes(roleId, Arrays.asList(pageCode));
        }
        log.info("step_2: 为角色({})关联新的按钮权限", roleId);
        if (!form.getCodes().isEmpty()) {
            List<AccessibleView> rolePermissions = form.getCodes().stream()
                    .map(permissionCode -> new AccessibleView(roleId, permissionCode, View.BUTTON))
                    .collect(toList());
            saveBatch(rolePermissions);
        }
        return Result.success(oper);
    }


    private void deleteRoleRelatedButtonsByPageCodes(Integer roleId, Collection<String> pageCodes) {
        String codes = Strings.join(pageCodes, '|');
        // 如：'^(Workplace)\..+' ,  '^(Monitor|Analysis|Workplace|BaseForm)\..+'
        String permissionCodeRegexp = String.format("^[%s]\\..+", codes);
        log.info("t_accessible_view.code 匹配的正则：{}", permissionCodeRegexp);
        baseMapper.deleteRoleAccessibleButtonsByRegexp(roleId, permissionCodeRegexp);
    }

}
